package main

import (
	"bytes"
	"log"
	"os/exec"
	"strings"
	"sync"

	_ "github.com/mattn/go-sqlite3"
)

var monitor = newMonitor()

type Monitor struct {
	allDevices map[string]*Device
	lock       *sync.RWMutex
}

func newMonitor() *Monitor {
	return &Monitor{
		allDevices: make(map[string]*Device),
		lock:       new(sync.RWMutex),
	}
}

func (mo *Monitor) setDevice(d *Device) {
	mo.lock.Lock()
	mo.allDevices[d.ID] = d
	mo.lock.Unlock()
}

func (mo *Monitor) getDevicesByFunc(f func(map[string]*Device)) {
	mo.lock.RLock()
	f(mo.allDevices)
	mo.lock.RUnlock()
}

func (mo *Monitor) getDevice(deviceID string) *Device {
	mo.lock.RLock()
	defer mo.lock.RUnlock()
	if d, exists := mo.allDevices[deviceID]; exists {
		return d
	}
	return nil
}

func (mo *Monitor) initAllDevice() {
	devices := mo.getDevices()
	for _, deviceID := range devices {
		NewDevice(deviceID)
	}
}

func (mo *Monitor) restartDevices() {
	mo.lock.Lock()
	for deviceID, device := range mo.allDevices {
		device.stop()
		NewDevice(deviceID)
	}
}

func (mo *Monitor) runCommand(c string, arg ...string) bytes.Buffer {
	cmd := exec.Command(c, arg...)
	cmd.Dir = "../"

	var out bytes.Buffer
	cmd.Stdout = &out

	cmd.Start()
	cmd.Wait()
	return out
}

func (mo *Monitor) getDevices() []string {
	out := mo.runCommand("adb", "devices")
	lines := strings.Split(out.String(), "\n")[1:]
	var devices = make([]string, 0, 20)

	for _, line := range lines {
		if line != "" {
			log.Println(strings.Split(line, "\t"))
			device := strings.Split(line, "\t")[0]
			devices = append(devices, device)
		}
	}
	return devices
}

func (mo *Monitor) getPackages(device_id string) []string {
	out := mo.runCommand("adb", "-s", device_id, "shell", "pm", "list", "packages")
	lines := strings.Split(out.String(), "\n")
	packages := make([]string, 0, 40)
	for _, line := range lines {
		if line != "" && len(line) >= 16 {
			if pName := line[8:16]; pName == "dkplugin" {
				packages = append(packages, line[8:])
			}
		}
	}
	return packages
}

func (mo *Monitor) initPacks(deviceID string) {
	packs := monitor.getPackages(deviceID)
	for _, pack := range packs {
		p := &Pack{DeviceID: deviceID, Name: pack, LoginStatus: UnknowLogin}
		db.Create(p)
	}
}

func main() {
	initDB()
	monitor.initAllDevice()
	initWeb()
}
